﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace AzukiMap.Tools
{
    /// <summary>
    /// データセットヘッダ
    /// </summary>
    public struct MeshDataSetHeader
    {
        public double MinX;			    //描画領域左下X 座標 
        public double MinY;			    //描画領域左下Y 座標 
        public double MaxX;			    //描画領域右上X 座標 
        public double MaxY;			    //描画領域右上Y 座標 
        public double PixelWidthX;		//1ピクセルの幅 
        public double PixelHeightY;		//1ピクセルの高さ 
        public int CountX;			//横ピクセルの数（W） 
        public int CountY;			//縦ピクセルの数（H） 
    }

    /// <summary>
    /// グリッドユーティリティ
    /// </summary>
    public class MeshDataSet<T>
    {
        private MeshDataSetHeader header;	//データセットヘッダー部 

        public MeshDataSetHeader Header
        {
            get { return header; }
            set { header = value; }
        }

        private T[] datas;

        public T[] Datas
        {
            get { return datas; }
            set { datas = value; }
        }

        /// <summary>
        /// ファイルの読み込み
        /// Gridﾌｧｲﾙを読み込み、ヘッダー、データをセット
        /// </summary>
        /// <param name="br"></param>
        /// <returns></returns>
        public void Read(System.IO.BinaryReader br)
        {
            //ヘッダー部読み込み
            ReadHeader(br);

            int size = header.CountX * header.CountY;
            datas = new T[size];
            //データ部分の読み込み
            for (int i = 0; i < size; i++)
            {
                if (typeof(T) == typeof(byte))
                {
                    datas[i] = (T)(object)br.ReadByte();
                }
                else if (typeof(T) == typeof(short))
                {
                    datas[i] = (T)(object)br.ReadInt16();
                }
                else if (typeof(T) == typeof(int))
                {
                    datas[i] = (T)(object)br.ReadInt32();
                }
                else if (typeof(T) == typeof(double))
                {
                    datas[i] = (T)(object)br.ReadDouble();
                }
            }

            return;
        }

        public void ReadHeader(System.IO.BinaryReader br)
        {
            //ヘッダー部読み込み
            header.MinX = br.ReadDouble();
            header.MinY = br.ReadDouble();
            header.MaxX = br.ReadDouble();
            header.MaxY = br.ReadDouble();
            header.PixelWidthX = br.ReadDouble();
            header.PixelHeightY = br.ReadDouble();
            header.CountX = br.ReadInt32();
            header.CountY = br.ReadInt32();
        }

        public void WriteHeader(System.IO.BinaryWriter bw)
        {
            //ヘッダー部書き込み
            bw.Write(header.MinX);
            bw.Write(header.MinY);
            bw.Write(header.MaxX);
            bw.Write(header.MaxY);
            bw.Write(header.PixelWidthX);
            bw.Write(header.PixelHeightY);
            bw.Write(header.CountX);
            bw.Write(header.CountY);
        }

        public void Write(System.IO.BinaryWriter bw)
        {
            //ヘッダー部書き込み
            WriteHeader(bw);

            int size = header.CountX * header.CountY;
            //データ部分の書き込み
            for (int i = 0; i < size; i++)
            {
                if (typeof(T) == typeof(byte))
                {
                    bw.Write((byte)(object)datas[i]);
                }
                else if (typeof(T) == typeof(short))
                {
                    bw.Write((short)(object)datas[i]);
                }
                else if (typeof(T) == typeof(int))
                {
                    bw.Write((int)(object)datas[i]);
                }
                else if (typeof(T) == typeof(double))
                {
                    bw.Write((double)(object)datas[i]);
                }
            }

        }

        /// <summary>
        /// Gridの該当セルにデータをセット
        /// </summary>
        /// <param name="val"></param>
        /// <param name="iy"></param>
        /// <param name="ix"></param>
        private void SetData(
            T val, //(i)セットする値
            int y,		//(i)Y方向セルID
            int x		//(i)X方向セルID
            )
        {
            if (y < 0 || y >= header.CountY || x < 0 || x >= header.CountX) return;
            if (datas == null) return;
            datas[y * header.CountX + x] = val;
        }

        /// <summary>
        /// Gridの該当セルのデータを参照
        /// </summary>
        /// <param name="iy"></param>
        /// <param name="ix"></param>
        /// <returns></returns>
        private T GetData(
            int y,		//(i)Y方向セルID
            int x		//(i)X方向セルID
            )
        {
            if (y < 0 || y >= header.CountY || x < 0 || x >= header.CountX) return (T)(object)-999.0;
            if (datas == null) return (T)(object)-999.0;
            return datas[y * header.CountX + x];
        }

    }
}
